home *** CD-ROM | disk | FTP | other *** search
- /*
- * serial_amiga.cpp - Serial device driver, AmigaOS specific stuff
- *
- * Basilisk II (C) 1997-2001 Christian Bauer
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
- #include <exec/types.h>
- #include <exec/memory.h>
- #include <exec/errors.h>
- #include <dos/dos.h>
- #include <dos/dosextens.h>
- #include <dos/dostags.h>
- #include <devices/serial.h>
- #include <devices/parallel.h>
- #include <proto/exec.h>
- #include <proto/dos.h>
-
- #include "sysdeps.h"
- #include "cpu_emulation.h"
- #include "main.h"
- #include "macos_util.h"
- #include "prefs.h"
- #include "serial.h"
- #include "serial_defs.h"
-
- #define DEBUG 0
- #include "debug.h"
-
- #define MONITOR 0
-
-
- // These messages are sent to the serial process
- const uint32 MSG_QUERY = 'qery'; // Query port status, return status in control_io
- const uint32 MSG_SET_PARAMS = 'setp'; // Set serial parameters (parameters in control_io)
- const uint32 MSG_SET_PAR_PARAMS = 'pstp'; // Set parallel parameters (parameters in control_io)
- const uint32 MSG_KILL_IO = 'kill'; // Kill pending I/O requests
- const uint32 MSG_BREAK = 'brek'; // Send break
- const uint32 MSG_RESET = 'rset'; // Reset channel
- const uint32 MSG_PRIME_IN = 'prin'; // Data input
- const uint32 MSG_PRIME_OUT = 'pout'; // Data output
-
- struct SerMessage : public Message {
- SerMessage(uint32 what_, const struct MsgPort *reply_port = NULL)
- {
- what = what_;
- mn_ReplyPort = (struct MsgPort *)reply_port;
- mn_Length = sizeof(*this);
- }
- uint32 what;
- uint32 pb;
- };
-
-
- // Driver private variables
- class ASERDPort : public SERDPort {
- public:
- ASERDPort(const char *dev)
- {
- device_name = dev;
- if (dev && dev[0] == '*') {
- is_parallel = true;
- device_name++;
- } else
- is_parallel = false;
- control_io = NULL;
- serial_proc = NULL;
- reply_port = NULL;
- }
-
- virtual ~ASERDPort()
- {
- }
-
- virtual int16 open(uint16 config);
- virtual int16 prime_in(uint32 pb, uint32 dce);
- virtual int16 prime_out(uint32 pb, uint32 dce);
- virtual int16 control(uint32 pb, uint32 dce, uint16 code);
- virtual int16 status(uint32 pb, uint32 dce, uint16 code);
- virtual int16 close(void);
-
- private:
- bool configure(uint16 config);
- void set_handshake(uint32 s, bool with_dtr);
- void send_to_proc(uint32 what, uint32 pb = 0);
- bool query(void);
- bool set_params(void);
- bool set_par_params(void);
- void conv_error(struct IOExtSer *io, uint32 dt);
- static void serial_func(void);
-
- const char *device_name; // Device name
- bool is_parallel; // Flag: Port is parallel
- IOExtSer *control_io; // IORequest for setting serial port characteristics etc.
-
- struct Process *serial_proc; // Serial device handler process
- bool proc_error; // Flag: process didn't initialize
- struct MsgPort *proc_port; // Message port of process, for communication with main task
- struct MsgPort *reply_port; // Reply port for communication with process
-
- uint8 err_mask; // shkErrs
- };
-
-
- // Global variables
- static void *proc_arg; // Argument to process
- extern struct Task *MainTask; // Pointer to main task (from main_amiga.cpp)
-
-
- /*
- * Initialization
- */
-
- void SerialInit(void)
- {
- // Read serial preferences and create structs for both ports
- the_serd_port[0] = new ASERDPort(PrefsFindString("seriala"));
- the_serd_port[1] = new ASERDPort(PrefsFindString("serialb"));
- }
-
-
- /*
- * Deinitialization
- */
-
- void SerialExit(void)
- {
- delete (ASERDPort *)the_serd_port[0];
- delete (ASERDPort *)the_serd_port[1];
- }
-
-
- /*
- * Open serial port
- */
-
- int16 ASERDPort::open(uint16 config)
- {
- // Don't open NULL name devices
- if (device_name == NULL)
- return openErr;
-
- // Init variables
- err_mask = 0;
-
- // Create message port
- reply_port = CreateMsgPort();
- if (reply_port == NULL)
- goto open_error;
-
- // Start process
- proc_error = false;
- proc_arg = this;
- SetSignal(0, SIGF_SINGLE);
- serial_proc = CreateNewProcTags(
- NP_Entry, (ULONG)serial_func,
- NP_Name, (ULONG)"Basilisk II Serial Task",
- NP_Priority, 1,
- TAG_END
- );
- if (serial_proc == NULL)
- goto open_error;
-
- // Wait for signal from process
- Wait(SIGF_SINGLE);
-
- // Initialization error? Then bail out
- if (proc_error)
- goto open_error;
-
- // Configure port
- configure(config);
- return noErr;
-
- open_error:
- serial_proc = NULL;
- if (reply_port) {
- DeleteMsgPort(reply_port);
- reply_port = NULL;
- }
- return openErr;
- }
-
-
- /*
- * Read data from port
- */
-
- int16 ASERDPort::prime_in(uint32 pb, uint32 dce)
- {
- // Send input command to serial process
- D(bug("primein\n"));
- read_done = false;
- read_pending = true;
- WriteMacInt32(input_dt + serdtDCE, dce);
- send_to_proc(MSG_PRIME_IN, pb);
- return 1; // Command in progress
- }
-
-
- /*
- * Write data to port
- */
-
- int16 ASERDPort::prime_out(uint32 pb, uint32 dce)
- {
- // Send output command to serial process
- D(bug("primeout\n"));
- write_done = false;
- write_pending = true;
- WriteMacInt32(output_dt + serdtDCE, dce);
- send_to_proc(MSG_PRIME_OUT, pb);
- return 1; // Command in progress
- }
-
-
- /*
- * Control calls
- */
-
- int16 ASERDPort::control(uint32 pb, uint32 dce, uint16 code)
- {
- D(bug("control(%ld)\n", (uint32)code));
- switch (code) {
- case 1: // KillIO
- send_to_proc(MSG_KILL_IO);
- return noErr;
-
- case kSERDConfiguration:
- if (configure(ReadMacInt16(pb + csParam)))
- return noErr;
- else
- return paramErr;
-
- case kSERDInputBuffer: {
- if (is_parallel)
- return noErr;
- int buf = ReadMacInt16(pb + csParam + 4) & 0xffffffc0;
- if (buf < 1024) // 1k minimum
- buf = 1024;
- D(bug(" buffer size is now %08lx\n", buf));
- control_io->io_RBufLen = buf;
- return set_params() ? noErr : paramErr;
- }
-
- case kSERDSerHShake:
- set_handshake(pb + csParam, false);
- return noErr;
-
- case kSERDSetBreak:
- if (!is_parallel)
- send_to_proc(MSG_BREAK);
- return noErr;
-
- case kSERDClearBreak:
- return noErr;
-
- case kSERDBaudRate:
- if (is_parallel)
- return noErr;
- control_io->io_Baud = ReadMacInt16(pb + csParam);
- D(bug(" baud rate %ld\n", control_io->io_Baud));
- return set_params() ? noErr : paramErr;
-
- case kSERDHandshake:
- case kSERDHandshakeRS232:
- set_handshake(pb + csParam, true);
- return noErr;
-
- case kSERDClockMIDI:
- if (is_parallel)
- return noErr;
- control_io->io_Baud = 31250;
- control_io->io_SerFlags = SERF_XDISABLED | SERF_SHARED;
- control_io->io_StopBits = 1;
- control_io->io_ReadLen = control_io->io_WriteLen = 8;
- return set_params() ? noErr : paramErr;
-
- case kSERDMiscOptions:
- case kSERDAssertDTR:
- case kSERDNegateDTR:
- case kSERDSetPEChar:
- case kSERDSetPEAltChar:
- case kSERDAssertRTS:
- case kSERDNegateRTS:
- return noErr; // Not supported under AmigaOS
-
- case kSERD115KBaud:
- if (is_parallel)
- return noErr;
- control_io->io_Baud = 115200;
- return set_params() ? noErr : paramErr;
-
- case kSERD230KBaud:
- case kSERDSetHighSpeed:
- if (is_parallel)
- return noErr;
- control_io->io_Baud = 230400;
- return set_params() ? noErr : paramErr;
-
- case kSERDResetChannel:
- send_to_proc(MSG_RESET);
- return noErr;
-
- default:
- printf("WARNING: SerialControl(): unimplemented control code %d\n", code);
- return controlErr;
- }
- }
-
-
- /*
- * Status calls
- */
-
- int16 ASERDPort::status(uint32 pb, uint32 dce, uint16 code)
- {
- D(bug("status(%ld)\n", (uint32)code));
- switch (code) {
- case kSERDInputCount:
- WriteMacInt32(pb + csParam, 0);
- if (!is_parallel) {
- if (!query())
- return noErr;
- D(bug("status(2) successful, returning %08lx\n", control_io->IOSer.io_Actual));
- WriteMacInt32(pb + csParam, control_io->IOSer.io_Actual);
- }
- return noErr;
-
- case kSERDStatus: {
- uint32 p = pb + csParam;
- WriteMacInt8(p + staCumErrs, cum_errors);
- cum_errors = 0;
- WriteMacInt8(p + staRdPend, read_pending);
- WriteMacInt8(p + staWrPend, write_pending);
- if (is_parallel) {
- WriteMacInt8(p + staXOffSent, 0);
- WriteMacInt8(p + staXOffHold, 0);
- WriteMacInt8(p + staCtsHold, 0);
- WriteMacInt8(p + staDsrHold, 0);
- WriteMacInt8(p + staModemStatus, dsrEvent | dcdEvent | ctsEvent);
- } else {
- query();
- WriteMacInt8(p + staXOffSent,
- (control_io->io_Status & IO_STATF_XOFFREAD ? xOffWasSent : 0)
- | (control_io->io_Status & (1 << 6) ? dtrNegated : 0)); // RTS
- WriteMacInt8(p + staXOffHold, control_io->io_Status & IO_STATF_XOFFWRITE);
- WriteMacInt8(p + staCtsHold, control_io->io_Status & (1 << 4)); // CTS
- WriteMacInt8(p + staDsrHold, control_io->io_Status & (1 << 3)); // DSR
- WriteMacInt8(p + staModemStatus,
- (control_io->io_Status & (1 << 3) ? 0 : dsrEvent)
- | (control_io->io_Status & (1 << 2) ? riEvent : 0)
- | (control_io->io_Status & (1 << 5) ? 0 : dcdEvent)
- | (control_io->io_Status & (1 << 4) ? 0 : ctsEvent)
- | (control_io->io_Status & IO_STATF_READBREAK ? breakEvent : 0));
- }
- return noErr;
- }
-
- default:
- printf("WARNING: SerialStatus(): unimplemented status code %d\n", code);
- return statusErr;
- }
- }
-
-
- /*
- * Close serial port
- */
-
- int16 ASERDPort::close()
- {
- // Stop process
- if (serial_proc) {
- SetSignal(0, SIGF_SINGLE);
- Signal(&serial_proc->pr_Task, SIGBREAKF_CTRL_C);
- Wait(SIGF_SINGLE);
- }
-
- // Delete reply port
- if (reply_port) {
- DeleteMsgPort(reply_port);
- reply_port = NULL;
- }
- return noErr;
- }
-
-
- /*
- * Configure serial port with MacOS config word
- */
-
- bool ASERDPort::configure(uint16 config)
- {
- D(bug(" configure %04lx\n", (uint32)config));
- if (is_parallel)
- return true;
-
- // Set number of stop bits
- switch (config & 0xc000) {
- case stop10:
- control_io->io_StopBits = 1;
- break;
- case stop20:
- control_io->io_StopBits = 2;
- break;
- default:
- return false;
- }
-
- // Set parity mode
- switch (config & 0x3000) {
- case noParity:
- control_io->io_SerFlags &= ~SERF_PARTY_ON;
- break;
- case oddParity:
- control_io->io_SerFlags |= SERF_PARTY_ON | SERF_PARTY_ODD;
- break;
- case evenParity:
- control_io->io_SerFlags |= SERF_PARTY_ON;
- control_io->io_SerFlags &= ~SERF_PARTY_ODD;
- break;
- default:
- return false;
- }
-
- // Set number of data bits
- switch (config & 0x0c00) {
- case data5:
- control_io->io_ReadLen = control_io->io_WriteLen = 5;
- break;
- case data6:
- control_io->io_ReadLen = control_io->io_WriteLen = 6;
- break;
- case data7:
- control_io->io_ReadLen = control_io->io_WriteLen = 7;
- break;
- case data8:
- control_io->io_ReadLen = control_io->io_WriteLen = 8;
- break;
- }
-
- // Set baud rate
- control_io->io_Baud = 115200 / ((config & 0x03ff) + 2);
- return set_params();
- }
-
-
- /*
- * Set serial handshaking
- */
-
- void ASERDPort::set_handshake(uint32 s, bool with_dtr)
- {
- D(bug(" set_handshake %02x %02x %02x %02x %02x %02x %02x %02x\n",
- ReadMacInt8(s + 0), ReadMacInt8(s + 1), ReadMacInt8(s + 2), ReadMacInt8(s + 3),
- ReadMacInt8(s + 4), ReadMacInt8(s + 5), ReadMacInt8(s + 6), ReadMacInt8(s + 7)));
-
- err_mask = ReadMacInt8(s + shkErrs);
-
- if (is_parallel) {
-
- // Parallel handshake
- if (with_dtr) {
- if (ReadMacInt8(s + shkFCTS) || ReadMacInt8(s + shkFDTR))
- ((IOExtPar *)control_io)->io_ParFlags |= PARF_ACKMODE;
- else
- ((IOExtPar *)control_io)->io_ParFlags &= ~PARF_ACKMODE;
- } else {
- if (ReadMacInt8(s + shkFCTS))
- ((IOExtPar *)control_io)->io_ParFlags |= PARF_ACKMODE;
- else
- ((IOExtPar *)control_io)->io_ParFlags &= ~PARF_ACKMODE;
- }
- set_par_params();
-
- } else {
-
- // Serial handshake
- if (ReadMacInt8(s + shkFXOn) || ReadMacInt8(s + shkFInX))
- control_io->io_SerFlags &= ~SERF_XDISABLED;
- else
- control_io->io_SerFlags |= SERF_XDISABLED;
-
- if (with_dtr) {
- if (ReadMacInt8(s + shkFCTS) || ReadMacInt8(s + shkFDTR))
- control_io->io_SerFlags |= SERF_7WIRE;
- else
- control_io->io_SerFlags &= ~SERF_7WIRE;
- } else {
- if (ReadMacInt8(s + shkFCTS))
- control_io->io_SerFlags |= SERF_7WIRE;
- else
- control_io->io_SerFlags &= ~SERF_7WIRE;
- }
- control_io->io_CtlChar = ReadMacInt16(s + shkXOn) << 16;
- set_params();
- }
- }
-
-
- /*
- * Send message to serial process
- */
-
- void ASERDPort::send_to_proc(uint32 what, uint32 pb)
- {
- D(bug("sending %08lx to serial_proc\n", what));
- SerMessage msg(what, reply_port);
- msg.pb = pb;
- PutMsg(proc_port, &msg);
- WaitPort(reply_port);
- GetMsg(reply_port);
- D(bug(" sent\n"));
- }
-
-
- /*
- * Query serial port status
- */
-
- bool ASERDPort::query(void)
- {
- send_to_proc(MSG_QUERY);
- return control_io->IOSer.io_Error == 0;
- }
-
-
- /*
- * Set serial parameters
- */
-
- bool ASERDPort::set_params(void)
- {
- // Set/clear RadBoogie
- UBYTE flags = control_io->io_SerFlags;
- if (!(flags & SERF_PARTY_ON) && (flags & SERF_XDISABLED) && control_io->io_ReadLen == 8)
- control_io->io_SerFlags |= SERF_RAD_BOOGIE;
- else
- control_io->io_SerFlags &= ~SERF_RAD_BOOGIE;
-
- // Send message to serial process
- send_to_proc(MSG_SET_PARAMS);
- return control_io->IOSer.io_Error == 0;
- }
-
-
- /*
- * Set parallel parameters
- */
-
- bool ASERDPort::set_par_params(void)
- {
- send_to_proc(MSG_SET_PAR_PARAMS);
- return control_io->IOSer.io_Error == 0;
- }
-
-
- /*
- * Convert AmigaOS error code to MacOS error code, set serdtResult and cum_errors
- */
-
- void ASERDPort::conv_error(struct IOExtSer *io, uint32 dt)
- {
- int16 oserr;
- uint8 cum;
-
- BYTE err = io->IOSer.io_Error;
- if (err == 0 || err == IOERR_NOCMD) {
- oserr = 0;
- cum = 0;
- } else {
- if (is_parallel) {
- oserr = (err_mask & framingErr) ? rcvrErr : 0;
- cum = framingErr;
- } else {
- switch (io->IOSer.io_Error) {
- case SerErr_DetectedBreak:
- oserr = breakRecd;
- cum = breakErr;
- break;
- case SerErr_ParityErr:
- oserr = (err_mask & parityErr) ? rcvrErr : 0;
- cum = parityErr;
- break;
- case SerErr_BufOverflow:
- oserr = (err_mask & swOverrunErr) ? rcvrErr : 0;
- cum = swOverrunErr;
- break;
- case SerErr_LineErr:
- oserr = (err_mask & hwOverrunErr) ? rcvrErr : 0;
- cum = hwOverrunErr;
- break;
- default:
- oserr = (err_mask & framingErr) ? rcvrErr : 0;
- cum = framingErr;
- break;
- }
- }
- }
-
- WriteMacInt32(dt + serdtResult, oserr);
- cum_errors |= cum;
- }
-
-
- /*
- * Process for communication with the serial.device
- */
-
- __saveds void ASERDPort::serial_func(void)
- {
- struct ASERDPort *obj = (ASERDPort *)proc_arg;
- struct MsgPort *proc_port = NULL, *io_port = NULL, *control_port = NULL;
- struct IOExtSer *read_io = NULL, *write_io = NULL, *control_io = NULL;
- uint8 orig_params[sizeof(struct IOExtSer)];
- bool opened = false;
- ULONG io_mask = 0, proc_port_mask = 0;
-
- // Default: error occured
- obj->proc_error = true;
-
- // Create message port for communication with main task
- proc_port = CreateMsgPort();
- if (proc_port == NULL)
- goto quit;
- proc_port_mask = 1 << proc_port->mp_SigBit;
-
- // Create message ports for serial.device I/O
- io_port = CreateMsgPort();
- if (io_port == NULL)
- goto quit;
- io_mask = 1 << io_port->mp_SigBit;
- control_port = CreateMsgPort();
- if (control_port == NULL)
- goto quit;
-
- // Create IORequests
- read_io = (struct IOExtSer *)CreateIORequest(io_port, sizeof(struct IOExtSer));
- write_io = (struct IOExtSer *)CreateIORequest(io_port, sizeof(struct IOExtSer));
- control_io = (struct IOExtSer *)CreateIORequest(control_port, sizeof(struct IOExtSer));
- if (read_io == NULL || write_io == NULL || control_io == NULL)
- goto quit;
- read_io->IOSer.io_Message.mn_Node.ln_Type = 0; // Avoid CheckIO() bug
- write_io->IOSer.io_Message.mn_Node.ln_Type = 0;
- control_io->IOSer.io_Message.mn_Node.ln_Type = 0;
-
- // Parse device name
- char dev_name[256];
- ULONG dev_unit;
- if (sscanf(obj->device_name, "%[^/]/%ld", dev_name, &dev_unit) < 2)
- goto quit;
-
- // Open device
- if (obj->is_parallel)
- ((IOExtPar *)read_io)->io_ParFlags = PARF_SHARED;
- else
- read_io->io_SerFlags = SERF_SHARED | SERF_7WIRE;
- if (OpenDevice((UBYTE *)dev_name, dev_unit, (struct IORequest *)read_io, 0) || read_io->IOSer.io_Device == NULL)
- goto quit;
- opened = true;
-
- // Copy IORequests
- memcpy(write_io, read_io, sizeof(struct IOExtSer));
- memcpy(control_io, read_io, sizeof(struct IOExtSer));
-
- // Attach control_io to control_port and set default values
- control_io->IOSer.io_Message.mn_ReplyPort = control_port;
- if (!obj->is_parallel) {
- control_io->io_CtlChar = SER_DEFAULT_CTLCHAR;
- control_io->io_RBufLen = 64;
- control_io->io_ExtFlags = 0;
- control_io->io_Baud = 9600;
- control_io->io_BrkTime = 250000;
- control_io->io_ReadLen = control_io->io_WriteLen = 8;
- control_io->io_StopBits = 1;
- control_io->io_SerFlags = SERF_SHARED;
- control_io->IOSer.io_Command = SDCMD_SETPARAMS;
- DoIO((struct IORequest *)control_io);
- memcpy(orig_params, &(control_io->io_CtlChar), (uint8 *)&(control_io->io_Status) - (uint8 *)&(control_io->io_CtlChar));
- }
-
- // Initialization went well, inform main task
- obj->proc_port = proc_port;
- obj->control_io = control_io;
- obj->proc_error = false;
- Signal(MainTask, SIGF_SINGLE);
-
- // Main loop
- for (;;) {
-
- // Wait for I/O and messages (CTRL_C is used for quitting the task)
- ULONG sig = Wait(proc_port_mask | io_mask | SIGBREAKF_CTRL_C);
-
- // Main task wants to quit us
- if (sig & SIGBREAKF_CTRL_C)
- break;
-
- // Main task sent a command to us
- if (sig & proc_port_mask) {
- struct SerMessage *msg;
- while (msg = (SerMessage *)GetMsg(proc_port)) {
- D(bug("serial_proc received %08lx\n", msg->what));
- switch (msg->what) {
- case MSG_QUERY:
- control_io->IOSer.io_Command = SDCMD_QUERY;
- DoIO((struct IORequest *)control_io);
- D(bug(" query returned %08lx, actual %08lx\n", control_io->IOSer.io_Error, control_io->IOSer.io_Actual));
- break;
-
- case MSG_SET_PARAMS:
- // Only send SDCMD_SETPARAMS when configuration has changed
- if (memcmp(orig_params, &(control_io->io_CtlChar), (uint8 *)&(control_io->io_Status) - (uint8 *)&(control_io->io_CtlChar))) {
- memcpy(orig_params, &(control_io->io_CtlChar), (uint8 *)&(control_io->io_Status) - (uint8 *)&(control_io->io_CtlChar));
- memcpy(&(read_io->io_CtlChar), &(control_io->io_CtlChar), (uint8 *)&(control_io->io_Status) - (uint8 *)&(control_io->io_CtlChar));
- memcpy(&(write_io->io_CtlChar), &(control_io->io_CtlChar), (uint8 *)&(control_io->io_Status) - (uint8 *)&(control_io->io_CtlChar));
- control_io->IOSer.io_Command = SDCMD_SETPARAMS;
- D(bug(" params %08lx %08lx %08lx %08lx %08lx %08lx\n", control_io->io_CtlChar, control_io->io_RBufLen, control_io->io_ExtFlags, control_io->io_Baud, control_io->io_BrkTime, *(uint32 *)((uint8 *)control_io + 76)));
- DoIO((struct IORequest *)control_io);
- D(bug(" set_parms returned %08lx\n", control_io->IOSer.io_Error));
- }
- break;
-
- case MSG_SET_PAR_PARAMS:
- control_io->IOSer.io_Command = PDCMD_SETPARAMS;
- DoIO((struct IORequest *)control_io);
- D(bug(" set_par_parms returned %08lx\n", control_io->IOSer.io_Error));
- break;
-
- case MSG_BREAK:
- control_io->IOSer.io_Command = SDCMD_BREAK;
- DoIO((struct IORequest *)control_io);
- D(bug(" break returned %08lx\n", control_io->IOSer.io_Error));
- break;
-
- case MSG_RESET:
- control_io->IOSer.io_Command = CMD_RESET;
- DoIO((struct IORequest *)control_io);
- D(bug(" reset returned %08lx\n", control_io->IOSer.io_Error));
- break;
-
- case MSG_KILL_IO:
- AbortIO((struct IORequest *)read_io);
- AbortIO((struct IORequest *)write_io);
- WaitIO((struct IORequest *)read_io);
- WaitIO((struct IORequest *)write_io);
- obj->read_pending = obj->write_pending = false;
- obj->read_done = obj->write_done = false;
- break;
-
- case MSG_PRIME_IN:
- read_io->IOSer.io_Message.mn_Node.ln_Name = (char *)msg->pb;
- read_io->IOSer.io_Data = Mac2HostAddr(ReadMacInt32(msg->pb + ioBuffer));
- read_io->IOSer.io_Length = ReadMacInt32(msg->pb + ioReqCount);
- read_io->IOSer.io_Actual = 0;
- read_io->IOSer.io_Command = CMD_READ;
- D(bug("serial_proc receiving %ld bytes from %08lx\n", read_io->IOSer.io_Length, read_io->IOSer.io_Data));
- SendIO((struct IORequest *)read_io);
- break;
-
- case MSG_PRIME_OUT: {
- write_io->IOSer.io_Message.mn_Node.ln_Name = (char *)msg->pb;
- write_io->IOSer.io_Data = Mac2HostAddr(ReadMacInt32(msg->pb + ioBuffer));
- write_io->IOSer.io_Length = ReadMacInt32(msg->pb + ioReqCount);
- write_io->IOSer.io_Actual = 0;
- write_io->IOSer.io_Command = CMD_WRITE;
- D(bug("serial_proc transmitting %ld bytes from %08lx\n", write_io->IOSer.io_Length, write_io->IOSer.io_Data));
- #if MONITOR
- bug("Sending serial data:\n");
- uint8 *adr = Mac2HostAddr(ReadMacInt32(msg->pb + ioBuffer));
- for (int i=0; i<len; i++) {
- bug("%02lx ", adr[i]);
- }
- bug("\n");
- #endif
- SendIO((struct IORequest *)write_io);
- break;
- }
- }
- D(bug(" serial_proc replying\n"));
- ReplyMsg(msg);
- }
- }
-
- // I/O operation completed
- if (sig & io_mask) {
- struct IOExtSer *io;
- while (io = (struct IOExtSer *)GetMsg(io_port)) {
- if (io == read_io) {
- D(bug("read_io complete, %ld bytes received, error %ld\n", read_io->IOSer.io_Actual, read_io->IOSer.io_Error));
- uint32 pb = (uint32)read_io->IOSer.io_Message.mn_Node.ln_Name;
- #if MONITOR
- bug("Receiving serial data:\n");
- uint8 *adr = Mac2HostAddr(ReadMacInt32(msg->pb + ioBuffer));
- for (int i=0; i<read_io->IOSer.io_Actual; i++) {
- bug("%02lx ", adr[i]);
- }
- bug("\n");
- #endif
- WriteMacInt32(pb + ioActCount, read_io->IOSer.io_Actual);
- obj->conv_error(read_io, obj->input_dt);
- obj->read_done = true;
- SetInterruptFlag(INTFLAG_SERIAL);
- TriggerInterrupt();
- } else if (io == write_io) {
- D(bug("write_io complete, %ld bytes sent, error %ld\n", write_io->IOSer.io_Actual, write_io->IOSer.io_Error));
- uint32 pb = (uint32)write_io->IOSer.io_Message.mn_Node.ln_Name;
- WriteMacInt32(pb + ioActCount, write_io->IOSer.io_Actual);
- obj->conv_error(write_io, obj->output_dt);
- obj->write_done = true;
- SetInterruptFlag(INTFLAG_SERIAL);
- TriggerInterrupt();
- }
- }
- }
- }
- quit:
-
- // Close everything
- if (opened) {
- if (CheckIO((struct IORequest *)write_io) == 0) {
- AbortIO((struct IORequest *)write_io);
- WaitIO((struct IORequest *)write_io);
- }
- if (CheckIO((struct IORequest *)read_io) == 0) {
- AbortIO((struct IORequest *)read_io);
- WaitIO((struct IORequest *)read_io);
- }
- CloseDevice((struct IORequest *)read_io);
- }
- if (control_io)
- DeleteIORequest(control_io);
- if (write_io)
- DeleteIORequest(write_io);
- if (read_io)
- DeleteIORequest(read_io);
- if (control_port)
- DeleteMsgPort(control_port);
- if (io_port)
- DeleteMsgPort(io_port);
-
- // Send signal to main task to confirm termination
- Forbid();
- Signal(MainTask, SIGF_SINGLE);
- }
-